package com.mebs.model.logistics;

import com.mebs.model.*;
import com.mebs.model.inventory.*;

import javax.persistence.*;

import org.jt.jet.annotation.Field;
import org.jt.jet.annotation.ArgumentType;
import org.jt.jet.util.JetUtils;
import static org.hibernate.proxy.HibernateProxyHelper.getClassWithoutInitializingProxy;

import java.util.Set;

/**
 * Created by Sergey Prasolov, sap@jensentechnologies.com
 *
 * Date: Feb 20, 2006, 2:32:50 PM
 */
@Entity
@Table(name = "LOGISTICS")
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class LogisticsOperation extends Requirement {
    @Column(name = "Comments", nullable = true, length = 1024)
    private String comments;

    @OneToOne(mappedBy = "legOperation", fetch = FetchType.LAZY)
    @Field(type = ArgumentType.INSTANCE)
    private Leg linkedLeg;

    @ManyToMany(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY)
    @JoinTable(name = "LOGISTICS_ORDER",
        joinColumns = {@JoinColumn(name = "LogisticsOperationId")},
        inverseJoinColumns = {@JoinColumn(name = "OrderId")})
    @Field(type = ArgumentType.INSTANCE)
    private Set<AbstractOrder> orders;

    /**
     * Constructors
     */
    protected LogisticsOperation()
    {
    }

    /**
     * Getters-setters
     */
    public String getComments()
    {
        return comments;
    }

    public void setComments(String comments)
    {
        this.comments = comments;
    }

    public Leg getLinkedLeg()
    {
        return linkedLeg;
    }

    public void setLinkedLeg(Leg linkedLeg)
    {
        this.linkedLeg = linkedLeg;
    }

    public Set<AbstractOrder> getOrders()
    {
        return orders;
    }

    public void setOrders(Set<AbstractOrder> orders)
    {
        this.orders = orders;
    }

    @Transient
    public boolean isUsedForPurchaseOrder()
    {
        Set<? extends AbstractOrder> orders = getOrders();
        if (! JetUtils.isEmpty(orders))
            return orders.toArray()[0] instanceof PurchaseOrder;
        else return false;
    }

    @Transient
    public boolean isUsedForRelocationOrder()
    {
        Set<? extends AbstractOrder> orders = getOrders();
        if (! JetUtils.isEmpty(orders))
            return orders.toArray()[0] instanceof RelocationOrder;
        else return false;
    }

    @Transient
    public boolean canUnbindOrder(AbstractOrder order)
    {
        //boolean ret = true;

        if (order instanceof RelocationOrder) {
            Set<RelocationPiece> pieces = ((RelocationOrder) order).getPieces();
            for (RelocationPiece piece : pieces) {
                if (this.equals(piece.getAir()) ||
                    this.equals(piece.getOceanContainer().getOcean()) ||
                    this.equals(piece.getTruck())) {
                    return false;
                    //ret = false;
                    //break;
                }
            }
        } else if (order instanceof PurchaseOrder) {
            Set<OrderItem> items = ((PurchaseOrder) order).getItems();
            for (OrderItem item : items) {
                for (BoxItem boxItem : item.getBoxItems()) {
                    if (this.equals(boxItem.getBox().getAir()) ||
                        this.equals(boxItem.getBox().getOceanContainer().getOcean()) ||
                        this.equals(boxItem.getBox().getTruck())) {
                        return false;
                        //ret = false;
                        //break;
                    }
                }
                //if (! ret) break;
            }
        }
        return true;
    }

    @Override
    public int hashCode()
    {
        if (getId() == null) return super.hashCode();
        return getId().hashCode();
    }

    @Override
    public boolean equals(Object o)
    {
        if (o == null) return false;
        if (this == o) return true;
        if (getId() == null) return false;
        if (getClassWithoutInitializingProxy(o) != getClassWithoutInitializingProxy(this) &&
            ! getClassWithoutInitializingProxy(o).isAssignableFrom(LogisticsOperation.class))
            return false;
        final LogisticsOperation that = (LogisticsOperation) o;
        return getId().equals(that.getId());
    }
}
